#include <inctypes.h>
#include <incctrls.h>

/* =================== 硬件相关 =================== */

/*********************************************************************************
 * 
 * drv_s3c2440_systick_init - 初始化SYSTICK
 * 
 * DESCRIPTION
 */

static void drv_s3c2440_systick_init (void)
    {
    u32_t cfgreg;

    /* 读取定时器的配置寄存器0 */

    cfgreg = hal_io32_read (S3C2440_REG_TCFG0);

    /* 清除 配置寄存器 的 8~15位 */

    cfgreg &= 0xFFFF00FF;

    /* 设置定时器4预分频值为 255 */

    cfgreg |= 0xFF00;
    hal_io32_write (S3C2440_REG_TCFG0, cfgreg);

    /* 读取定时器的配置寄存器1 */

    cfgreg = hal_io32_read (S3C2440_REG_TCFG1);

    /* 选择定时器4的选通输入为 0000 = 1/2 */

    cfgreg &= 0xFFF0FFFF;

    /* 写入定时器的配置寄存器1 */

    hal_io32_write (S3C2440_REG_TCFG1, cfgreg);

    /* 设置定时器4的计数预装载值为0x41 */

    hal_io32_write (S3C2440_REG_TCNTB4, 0x41);

    /* 启动定时器 | 设置为重载模式 */

    cfgreg =  hal_io32_read (S3C2440_REG_TCON);
    cfgreg &= 0xFF8FFFFF;
    hal_io32_write (S3C2440_REG_TCON, cfgreg);   /* 清0 20~22位 */
    cfgreg =  hal_io32_read (S3C2440_REG_TCON);
    cfgreg |= 0x700000;
    hal_io32_write (S3C2440_REG_TCON, cfgreg);   /* 启动定时器4 | 更新 TCNTB4 寄存器 | 自动重载 */
    cfgreg =  hal_io32_read (S3C2440_REG_TCON);
    cfgreg &= (~0x200000);
    hal_io32_write (S3C2440_REG_TCON, cfgreg);   /* TCNTB4 无更新 */

    return;
    }

/* =================== 中断服务函数 =================== */

/*********************************************************************************
 * 
 * drv_systick_isrhandle - systick 设备驱动程序中断回调函数
 * 
 * DESCRIPTION
 */

static drvstus_t drv_systick_isrhandle
    (
    uint_t ifdidx,
    void * devp,
    void * sframe
    )
    {
    
    /* 增加当前运行的进程的时间片计数 */

    krl_inc_thdtick (krl_sched_return_curthd ());

    /* 打印 字符串 */

    kprintf ("systick handle is run!\r\n");

    return OK;
    }

/* =================== IO 分发函数 =================== */

/*********************************************************************************
 * 
 * drv_systick_open - systick 设备驱动程序的打开函数 
 * 
 * DESCRIPTION
 */

static drvstus_t drv_systick_open
    (
    device_t * devp,
    void *     iopack
    )
    {
    return ERROR;
    }

/*********************************************************************************
 * 
 * drv_systick_close - systick 设备驱动程序关闭函数
 * 
 * DESCRIPTION
 */

static drvstus_t drv_systick_close
    (
    device_t * devp,
    void *     iopack
    )
    {
    return ERROR;
    }

/*********************************************************************************
 * 
 * drv_systick_read - systick 设备驱动程序读取函数
 * 
 * DESCRIPTION
 */

static drvstus_t drv_systick_read
    (
    device_t * devp,
    void *     iopack
    )
    {
    return ERROR;
    }

/*********************************************************************************
 * 
 * drv_systick_write - systick 设备驱动程序写入函数
 * 
 * DESCRIPTION
 */

static drvstus_t drv_systick_write
    (
    device_t * devp,
    void *     iopack
    )
    {
    return ERROR;
    }

/*********************************************************************************
 * 
 * drv_systick_lseek - systick 设备驱动程序调整读写位置函数
 * 
 * DESCRIPTION
 */

static drvstus_t drv_systick_lseek
    (
    device_t * devp,
    void *     iopack
    )
    {
    return ERROR;
    }

/*********************************************************************************
 * 
 * drv_systick_ioctl - systick 设备驱动程序控制函数
 * 
 * DESCRIPTION
 */

static drvstus_t drv_systick_ioctl
    (
    device_t * devp,
    void *     iopack
    )
    {
    return ERROR;
    }

/*********************************************************************************
 * 
 * drv_systick_start - systick 设备驱动程序开始函数
 * 
 * DESCRIPTION
 */

static drvstus_t drv_systick_start
    (
    device_t * devp,
    void *     iopack
    )
    {
    return ERROR;
    }

/*********************************************************************************
 * 
 * drv_systick_stop - systick 设备驱动程序停止函数
 * 
 * DESCRIPTION
 */

static drvstus_t drv_systick_stop
    (
    device_t * devp,
    void *     iopack
    )
    {
    return ERROR;
    }

/*********************************************************************************
 * 
 * drv_systick_powerset - systick 设备驱动程序的设置电源函数
 * 
 * DESCRIPTION
 */

static drvstus_t drv_systick_powerset
    (
    device_t * devp,
    void *     iopack
    )
    {
    return ERROR;
    }

/*********************************************************************************
 * 
 * drv_systick_enumdev - systick 设备驱动程序枚举设备函数
 * 
 * DESCRIPTION
 */

static drvstus_t drv_systick_enumdev
    (
    device_t * devp,
    void *     iopack
    )
    {
    return ERROR;
    }

/*********************************************************************************
 * 
 * drv_systick_flush - systick 设备驱动程序刷新缓存函数
 * 
 * DESCRIPTION
 */

static drvstus_t drv_systick_flush
    (
    device_t * devp,
    void *     iopack
    )
    {
    return ERROR;
    }

/*********************************************************************************
 * 
 * drv_systick_shutdown - systick 设备驱动程序关机函数
 * 
 * DESCRIPTION
 */

static drvstus_t drv_systick_shutdown
    (
    device_t * devp,
    void *     iopack
    )
    {
    return ERROR;
    }

/* =================== 设置相关结构体的域 =================== */

/*********************************************************************************
 * 
 * drv_systick_set_driver - 填写 driver_t 结构示例变量的相关域
 * 
 * DESCRIPTION
 */

static void drv_systick_set_driver
    (
    driver_t * drvp
    )
    {
    
    /* 设置 I/O 功能分发函数 */

    drvp->dipfunc[IOIF_CODE_OPEN]     = drv_systick_open;
    drvp->dipfunc[IOIF_CODE_CLOSE]    = drv_systick_close;
    drvp->dipfunc[IOIF_CODE_READ]     = drv_systick_read;
    drvp->dipfunc[IOIF_CODE_WRITE]    = drv_systick_write;
    drvp->dipfunc[IOIF_CODE_LSEEK]    = drv_systick_lseek;
    drvp->dipfunc[IOIF_CODE_IOCTL]    = drv_systick_ioctl;
    drvp->dipfunc[IOIF_CODE_START]    = drv_systick_start;
    drvp->dipfunc[IOIF_CODE_STOP]     = drv_systick_stop;
    drvp->dipfunc[IOIF_CODE_POWERSET] = drv_systick_powerset;
    drvp->dipfunc[IOIF_CODE_ENUMDEV]  = drv_systick_enumdev;
    drvp->dipfunc[IOIF_CODE_FLUSH]    = drv_systick_flush;
    drvp->dipfunc[IOIF_CODE_SHUTDOWN] = drv_systick_shutdown;

    /* 设置驱动名 */

    drvp->name = "systick_drv";

    return;
    }

/*********************************************************************************
 * 
 * drv_systick_set_device - 填写 device_t 结构示例变量的相关域
 * 
 * DESCRIPTION
 */

static void drv_systick_set_device
    (
    device_t * devp,
    driver_t * drvp
    )
    {

    /* 填写设备标志, 独占使用设备 */

    devp->flag = DEV_ATTRFLG_SHARE;

    /* 填写设备状态 (普通状态, 设备可用) */

    devp->status = DEV_ATTRSTS_NORMAL;

    /* 填写设备类型 (主设备号, 次设备号) */

    devp->id.majtype = DEVICE_CLASSITY_SYSTICK; /* SYSTICK 类型设备 */
    devp->id.subtype = 0;                       /* 0 */

    /* 填写设备序号 */

    devp->id.index = 0;                         /* 0 */

    /* 填写设备名 */

    devp->name = "systick0";

    return;
    }

/* =================== 驱动程序框架 =================== */

/*********************************************************************************
 * 
 * drv_systick_entry - systick 设备驱动程序入口函数
 * 
 * DESCRIPTION
 */

drvstus_t drv_systick_entry
    (
    driver_t * drvp,
    uint_t     value,
    void *     param
    )
    {

    /* 判断参数有效性 */

    if (drvp == NULL)
        {
        return ERROR;
        }

    /* 创建 device_t 结构的实例变量 */

    device_t * devp = dev_create_devicedsc ();

    if (devp == NULL)
        {
        return ERROR;
        }

    /* 填写 driver_t 和 device_t 的域 */

    drv_systick_set_driver (drvp);
    drv_systick_set_device (devp, drvp);

    /* 将设备添加进驱动管理链表 */

    if (dev_add_device_to_driver (devp, drvp) == ERROR)
        {
        
        /* 设备加入驱动失败, 释放资源 (删除设备数据结构的实例变量) */

        goto return_step;
        }

    /* 将设备注册进内核系统 */

    if (krl_dev_register_device (devp) ==  ERROR)
        {

        /* 设备注册进内核失败, 释放资源 (删除设备数据结构的实例变量) */

        goto return_step;
        }

    /* 注册驱动回调函数 */

    if (krl_dev_register_isrhandle (devp, drv_systick_isrhandle, 
                                    MAJINT_DESCIDX (S3C2440_TIMER4_IRQIDX)) == ERROR)
        {

        /* 设置中断回调失败, 释放资源 (删除设备数据结构的实例变量) */

        goto return_step;
        }

    /* 初始化硬件 (timer4) */

    drv_s3c2440_systick_init ();

    /* 
     * 使能 定时器4 硬件中断 
     * S3C2440_TIMER4_IRQIDX 是物理中断屏蔽位, 需要经过 MAJINT_DESCIDX 
     * 宏转换后才是内核 所需要的
     */

    if (intrpt_enable_irq (MAJINT_DESCIDX (S3C2440_TIMER4_IRQIDX)) == ERROR)
        {
        
        /* 使能定时器4中断失败 */

        goto return_step;
        }

    return OK;

return_step:

    /* 删除设备数据结构的实例变量 */   

    if (dev_delete_devicedsc (devp) == FALSE)
        {
        return ERROR; /* 删除失败 */
        }

    return ERROR;     /* 返回失败 */
    }

/*********************************************************************************
 * 
 * drv_systick_exit - systick 设备驱动程序出口函数
 * 
 * DESCRIPTION
 */

drvstus_t drv_systick_exit
    (
    driver_t * drvp,
    uint_t     value,
    void *     param
    )
    {
    return ERROR;
    }

